home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EuroCD 3
/
EuroCD 3.iso
/
Viewers
/
aMiPEG_1.0
/
src
/
ham8.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-24
|
12KB
|
469 lines
/*
* This source copes with all amiga-specific stuff as opening the screen, resizing
* it using user copper lists, etc.
*
* Copper-based resizing is now implemented, although no aspect ratio is taken care of.
*
* HAM6 is supported now.
*
* Michael Rausch 14-4-94 1:11:59
*
* Some fixes to allow for non-default monitors
*
* Miloslaw Smyk 21-2-96
*/
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/asl.h>
#include <cybergraphics/cgxvideo.h>
#include <pragmas/cgxvideo_pragmas.h>
#include <clib/cgxvideo_protos.h>
#include <libraries/asl.h>
#include <exec/memory.h>
#include <hardware/custom.h>
#include <graphics/copper.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/videocontrol.h>
#include <graphics/displayinfo.h>
#include <graphics/display.h>
#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/asyncio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "video.h"
#include "proto.h"
extern int ditherType;
extern int fullFlag;
extern void HAM8_Init(struct RastPort *); // kinda static
extern void HAM8_Init_lores(struct RastPort *);
extern void HAM6_Init_lores(struct RastPort *);
void (*HAM8_draw)(void *, int, int);
#define custom ((*(volatile struct Custom *)(0xdff000)))
struct IntuitionBase *IntuitionBase;
/* struct GfxBase *GfxBase; */
extern struct ExecBase *SysBase;
static struct Screen *screen;
static ULONG soerror = NULL;
int gfxver;
ULONG *kaiko = NULL;
int lores=TRUE, sdbl=TRUE, ham6=FALSE;
int max_x, max_y;
static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} }; /* Color 0 is 0x000*/
static void Quit(char *why, int failcode)
{
puts(why);
exit(failcode);
}
static void output_term(void)
{
close_timer();
if(input)
{
CloseAsync(input);
input = NULL;
}
if (screen)
{
FreeVPortCopLists(&(screen->ViewPort));
RemakeDisplay();
if(cyber_window)
CloseWindow(cyber_window);
CloseScreen(screen);
}
if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
if (GfxBase) CloseLibrary((struct Library *) GfxBase);
}
int get_ham_modeid(void)
{
struct ScreenModeRequester *scrMdReq;
int modeid = 0xffffffff;
if(scrMdReq = AllocAslRequestTags(ASL_ScreenModeRequest,
ASLSM_MinWidth, 200,
ASLSM_MinHeight, 200,
ASLSM_MinDepth, 6,
ASLSM_MaxDepth, 8,
ASLSM_PropertyFlags, DIPF_IS_HAM,
ASLSM_PropertyMask, DIPF_IS_HAM,
TAG_DONE))
{
if(AslRequestTags(scrMdReq, TAG_DONE))
modeid = scrMdReq->sm_DisplayID;
FreeAslRequest(scrMdReq);
}
return(modeid);
}
void InitColorDisplay(void)
{
atexit(output_term);
if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL)
Quit("graphics.library is too old, <V39",25);
if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",37))==NULL)
Quit("intuition.library is too old, <V39",25);
gfxver = GfxBase->LibNode.lib_Version;
if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr;
HAM8_draw = (void (*)(void *, int, int)) NoDitherImage; // method casting ... argh!
DoDitherImage = NoDitherImage;
if((modeid == 0xffffffff) && ((modeid = get_ham_modeid()) == 0xffffffff))
Quit("aMiPEG: unable to open HAM display...", 25);
}
/*
* Resize the display using a copper list. Nifty'n neat amiga feature.
*
* Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff.
*/
void ResizeDisplay(int w, int h)
{
struct UCopList *ucoplist;
static struct TagItem uCopTags[] = {
{ VC_NoColorPaletteLoad, TRUE },
{ VTAG_USERCLIP_SET, NULL },
{ VTAG_END_CM, NULL }};
int i,j,k, y, fp_each, locallores;
struct CopList *dspins;
struct CopIns *copins;
short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2;
ULONG id;
struct DimensionInfo dim_info;
BOOL quit = FALSE;
struct IntuiMessage *msg;
static char win_title[256];
static VLH_x, VLH_y;
static char first_time = TRUE;
if(ditherType == NO_DITHER) return;
if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER || ditherType == GRAY_DITHER || ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER)
{
if(ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER)
{
if(VLH && (VLH_x != w || VLH_y != h))
{
DetachVLayer(VLH);
DeleteVLayerHandle(VLH);
VLH = NULL;
}
if(!VLH && (VLH = CreateVLayerHandleTags(cyber_screen,
VOA_SrcType, SRCFMT_YCbCr16,
VOA_SrcWidth, w,
VOA_SrcHeight, h,
TAG_DONE)))
{
if(AttachVLayerTags(VLH, cyber_window, TAG_DONE))
Quit("Unable to attach video layer to a window", 25);
}
else
Quit("Unable to create a video layer", 25);
}
sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h);
SetWindowTitles(cyber_window, win_title, (UBYTE *)~0);
if(!fullFlag && first_time)
{
first_time = FALSE;
ModifyIDCMP(cyber_window, IDCMP_NEWSIZE);
// SizeWindow(cyber_window, w - 160, h - 120);
ChangeWindowBox(cyber_window, cyber_window->LeftEdge, cyber_window->TopEdge,
w + cyber_window->BorderLeft + cyber_window->BorderRight,
h + cyber_window->BorderTop + cyber_window->BorderBottom);
while(!quit)
{
WaitPort(cyber_window->UserPort);
while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort))
{
if(msg->Class == IDCMP_NEWSIZE)
quit = TRUE;
ReplyMsg((struct Message *)msg);
}
}
ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS | VANILLAKEY);
original_x = cyber_window->Width;
original_y = cyber_window->Height;
}
else
if(!first_time)
{
original_x = w;
original_y = h;
}
return;
}
id = modeid & MONITOR_ID_MASK;
if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0))
max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1;
else
max_y=200;
if(h>max_y)
sdbl=FALSE, max_y<<=1;
if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA)))
ham6 = TRUE;
if(ham6)
lores=TRUE;
locallores = lores && (w<=160);
max_x = (locallores ? 320 : 640);
switch(id)
{
case A2024_MONITOR_ID:
Quit("Get some colors, dude.", 25);
case DBLPAL_MONITOR_ID: /* ARGH! Kick their butts for this one! */
if(sdbl)
id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY;
else
id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY;
break;
case DBLNTSC_MONITOR_ID:
if(sdbl)
id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY;
else
id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY;
break;
case EURO72_MONITOR_ID:
if(sdbl)
id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY;
else
id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY;
break;
case VGA_MONITOR_ID:
if(sdbl)
id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY;
else
id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY;
break;
case PAL_MONITOR_ID:
case NTSC_MONITOR_ID:
/*
if(gfxver >= 40 && sdbl)
id = locallores ? id | LORESHAMSDBL_KEY: id | HIRESHAMSDBL_KEY;
else
*/
sdbl=FALSE, id = locallores ? id | HAM_KEY : id | HIRESHAM_KEY;
break;
default:
printf("ModeID 0x%x either doesn't support HAM or is unknown to aMiPEG.", id);
Quit("", 10);
}
if(!(screen=OpenScreenTags(NULL,
SA_DisplayID, id,
SA_Depth, ham6?6:8,
SA_Width, max_x,
SA_Colors, firstblack,
SA_Type, CUSTOMSCREEN|SCREENQUIET,
SA_Quiet, TRUE,
SA_Interleaved, !ham6, //TRUE,
SA_Overscan, OSCAN_STANDARD,
SA_MinimizeISG, TRUE,
SA_ErrorCode, &soerror,
TAG_END))) Quit("Couldn't open screen.",25);
if((screen->RastPort.BitMap->Depth == 6) && !ham6)
Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25);
if(cyber_window = OpenWindowTags(NULL,
WA_CustomScreen, screen,
WA_Flags, WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_BACKDROP,
WA_IDCMP, VANILLAKEY,
TAG_DONE))
;
if(lores) {
if(ham6)
{ // the new ham6 routines do not handle interleaved bitmaps anymore
HAM6_Init_lores(&(screen->RastPort));
HAM8_draw = HAM6_draw_lores;
DoDitherImage = ColorDitherImage_12bit;
} else {
HAM8_Init_lores(&(screen->RastPort));
HAM8_draw = HAM8_draw_lores;
DoDitherImage = ColorDitherImage_lores; // lacks kaiko support, actually
}
max_x >>=1;
} else {
HAM8_Init(&(screen->RastPort));
HAM8_draw = HAM8_draw_hires;
DoDitherImage = ColorDitherImage; // kaiko on one day
max_x >>=2;
}
if(noDisplayFlag)
HAM8_draw = (void (*)(void *, int, int)) NoDitherImage; // method casting ... argh!
/* the memory is freed upon exit in output_term via FreeVPortCopLists */
if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR)))
Quit("No memory for copper list.",25);
/* fiddle out some hardware values from this screen's init copper list */
dspins=screen->ViewPort.DspIns;
copins=dspins->CopIns;
for(i=dspins->Count-1; i>=0; i--, copins++)
{
j = copins->DESTDATA;
switch(copins->DESTADDR & 0xfff) // argh! kick 2.1 messes this up!
{
case (int)&((*(struct Custom *)(0)).bpl1mod):
last1=bpl1mod = j;
break;
case (int)&((*(struct Custom *)(0)).bpl2mod):
last2=bpl2mod = j;
break;
}
}
if(bpl1mod==-1 || bpl2mod==-1)
{
printf("ooops\n");
return; /* hmmm? */
}
if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE;
y = screen->Height;
(void) CINIT(ucoplist, y*3); /* ... instructions per line */
if(sdbl)
{
/*
* We abuse some of AGA's features here; double-scanning is implemented
* by applying bpl1mod to ALL planes on one line, bpl2mod on the next.
* Obviously, double-scanning enables some kind of internal chipmem cache.
* At least, it's faster. And (because of?) less copper instructions.
*/
fp_each = ((y*2)<<8) / (short)h;
for(k=fp_each, j=0; j<y; j++) /* for each line in the display */
{
if((k-=0x100)>=0x100) /* we still gotta double the line */
this1=bpl1mod;
else /* finally, we are ready; next one */
this1=bpl2mod, k=(k&0xff)+fp_each;
if((k-=0x100)>=0x100) /* we still gotta double the line */
this2=bpl1mod;
else /* finally, we are ready; next one */
this2=bpl2mod, k=(k&0xff)+fp_each;
if(last1!=this1 || last2!=this2)
CWAIT(ucoplist, j, 0);
if(last1!=this1)
{
CMOVE(ucoplist, custom.bpl1mod, this1);
last1=this1;
}
if(last2!=this2)
{
CMOVE(ucoplist, custom.bpl2mod, this2);
last2=this2;
}
}
} else {
/*
* No scan-doubling possible; most probably because of a pal/ntsc screen
* and no V40 graphics library available.
*/
bpl1mod -= screen->RastPort.BitMap->BytesPerRow;
fp_each = (y<<8) / (short)h;
for(k=fp_each, j=0; j<y; j++) /* for each line in the display */
{
if((k-=0x100)>=0x100) /* we still gotta double the line */
this1=bpl1mod;
else /* finally, we are ready; next one */
this1=bpl2mod, k=(k&0xff)+fp_each;
if(last1!=this1)
{
CWAIT(ucoplist, j, 0);
CMOVE(ucoplist, custom.bpl1mod, this1);
CMOVE(ucoplist, custom.bpl2mod, this1);
last1=this1;
}
}
}
/*
* Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in!
*/
CEND(ucoplist);
/* Set the freshly created user copper list */
//Forbid();
screen->ViewPort.UCopIns = ucoplist;
//Permit();
/* Enable user copper list clipping for this ViewPort. */
(void) VideoControl( screen->ViewPort.ColorMap, uCopTags );
RethinkDisplay();
}